package com.zyht.wechat.framework;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wx.core.process.WxApi;
import com.wx.core.vo.response.Fans;
import com.wx.entity.SysWxuser;
import com.wx.entity.WxFansUser;
import com.wx.model.dictionary.Constant;
import com.wx.service.SysWxTokenService;
import com.wx.service.WxFansUserService;
import com.zyht.bank.entity.AxdCustInfo;
import com.zyht.bank.service.AxdCustInfoService;
import com.zyht.common.util.HttpUtils;
import com.zyht.common.util.SpecialCharacterFilterUtil;
import com.zyht.wechat.WechatOperations;
import com.zyht.wechat.framework.env.WechatEnv;

/**
 * <b>描述：</b>微信统一鉴权,经过此拦截器的controller可以直接从request对象中获取openid和state<br/>
 * <b>作者：</b>Bob <br/>
 * <b>修改日期：</b>2017年1月15日 - 下午1:34:29<br/>
 */
public class OAuth2Interceptor implements HandlerInterceptor {

	// 拦截请求列表
	private List<String> handleUrlList;

	// 拦截指定前缀下的请求
	private String handlePrefix = "/oauth";

	@Resource
	private SysWxTokenService sysWxTokenService;

	@Resource
	private AxdCustInfoService axdCustInfoService;

	@Resource
	private WxFansUserService wxFansUserService;

	private boolean working = true;

	private boolean ismock = false;

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		String servletPath = request.getServletPath();
		String queryString = request.getQueryString();

		if (null != queryString)
			queryString = "?" + queryString;
		else
			queryString = "";
		if (isNeedHandle(servletPath, handler)) {
			HttpSession session = request.getSession();
			WxFansUser fan = (WxFansUser) session.getAttribute(Constant.CURRENT_USER_FANINFO_FROM_EVENT_VIEW);

			if (ismock) {
				if (null == session.getAttribute(Constant.CURRENT_USER_FANINFO_FROM_EVENT_VIEW)) {
					fan = new WxFansUser();
					fan.setHeadimgurl(
							"http://wx.qlogo.cn/mmopen/FiagVd5ak0QhUMP1ibU90kqfl5EcYFuucFl7WJdtiaNvh9hjz3QGKZS30yEhicy0a0KplLTxwCCVm7XBkNsSRLMDJl8Bn3iagclrz/0");
					fan.setNickname("张日波");
					fan.setOpenid("otOJYwFU38QKvoX5DfM2FwtuGESs");
					fan.setWxid("gh_eb02bd01cf9a");
					fan.setId(159);
					session.setAttribute(Constant.CURRENT_USER_FANINFO_FROM_EVENT_VIEW, fan);
				}
			}
			if (!working)
				return true;

			if (null != fan) {
				return true;
			}
			if (null == fan) {

				SysWxuser wxinfo = WechatEnv.wxuser;
				String appid = wxinfo.getAppid();
				String appSecret = wxinfo.getAppsecretd();

				String state = request.getParameter("state");
				String code = request.getParameter("code");

				if (!StringUtils.isEmpty(state) && !StringUtils.isEmpty(code)) {

					WechatOperations options = new WechatOperations();
					JSONObject json = options.getWebAccessToken(code, appid, appSecret);
					Integer errcode = json.getInteger("errcode");
					if (null != errcode && errcode.intValue() != 0) {
						return false;
					}
					String openId = json.getString("openid");
					if (!StringUtils.isEmpty(openId)) {
						WxFansUser wxfansUser = this.wxFansUserService.selectByOpenId(openId);
						if (null == wxfansUser) {
							String token = sysWxTokenService.getAccessToken(wxinfo);
							String requestUrl = WxApi.getFansInfoUrl(token, openId);
							String responseStr = HttpUtils.httpsGet(requestUrl);
							JSONObject jSONObject = JSON.parseObject(responseStr);
							Fans fans = JSON.parseObject(jSONObject.toString(), Fans.class);

							// 粉丝未关注
							if (null == fans || fans.getSubscribe().intValue() == 0) {
								request.getRequestDispatcher("/anon/sub/index").forward(request, response);
								return false;
							}

							wxfansUser = new WxFansUser();
							wxfansUser.setSubscribe(fans.getSubscribe().intValue());
							BeanUtils.copyProperties(fans, wxfansUser);
							// wxfansUser.setTags(StringUtils.join(fans.getTagid_list()));
							wxfansUser.setNickname(SpecialCharacterFilterUtil.utf8ToUnicode(fans.getNickname()));
							wxfansUser.setWxid(wxinfo.getWxid());
							if (fans.getSubscribe().intValue() == 1) {
								wxfansUser.setSubscribeTime(new Date());
							}
							this.wxFansUserService.insert(wxfansUser);

							// 保存用户信息
							AxdCustInfo custInfo = new AxdCustInfo();
							custInfo.setCreateTime(new Date());
							custInfo.setFanUserId(wxfansUser.getId());
							custInfo.setBandingStatus("0");
							axdCustInfoService.addOne(custInfo);
						}

						session.setAttribute(Constant.CURRENT_USER_FANINFO_FROM_EVENT_VIEW, wxfansUser);
						return true;
					} else {
						request.getRequestDispatcher("/" + servletPath).forward(request, response);
						return false;
					}
				} else {
					if (null == state) {
						state = "0";
					}
					String redirectUrl = getAbsolutelyServerPath(request).concat(servletPath).concat(queryString);
					redirectUrl = URLEncoder.encode(redirectUrl, StandardCharsets.UTF_8.toString());
					String authorizeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=".concat(appid)
							.concat("&redirect_uri=").concat(redirectUrl)
							.concat("&response_type=code&scope=snsapi_base&state=" + state).concat("#wechat_redirect");
					response.sendRedirect(authorizeUrl);
					return false;
				}
			}
		}
		return true;
	}

	private boolean isNeedHandle(String servletPath, Object handler) {
		if (handler.getClass().isAssignableFrom(HandlerMethod.class)) {
			HandlerMethod handlerMethod = ((HandlerMethod) handler);
			Object bean = handlerMethod.getBean();
			Oauth beanOauth = bean.getClass().getAnnotation(Oauth.class);
			Oauth oauth = handlerMethod.getMethodAnnotation(Oauth.class);
			if (beanOauth == null && oauth == null)
				return false;
			return true;
		}
		return (handleUrlList != null && handleUrlList.contains(servletPath))
				|| servletPath.startsWith(this.handlePrefix);
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {

	}

	public void setHandleUrlList(List<String> handleUrlList) {

		this.handleUrlList = handleUrlList;
	}

	public void setHandlePrefix(String handlePrefix) {

		this.handlePrefix = handlePrefix;
	}

	private final String getAbsolutelyServerPath(HttpServletRequest request) {
		String refererUrl = request.getScheme().concat("://").concat(request.getServerName());
		int port = request.getServerPort();
		if (port > 0 && port != 80) {
			refererUrl = refererUrl.concat(":").concat(port + "");
		}
		refererUrl = refererUrl.concat(request.getContextPath());
		return refererUrl;
	}

	public void setWorking(boolean working) {
		this.working = working;
	}

	public void setIsmock(boolean ismock) {
		this.ismock = ismock;
	}
}